<script setup lang="ts">
import {
  ArrowDown,
  CaretLeft,
  CaretRight,
  Headset,
  VideoPause,
  VideoPlay
} from '@element-plus/icons-vue'
import { onActivated, onDeactivated, reactive, ref, unref, watch } from 'vue'
import { Howl } from 'howler'
import { formatTrackTime } from '@/utils'
import { Local } from '@/utils/storage'
import { audioHistoryStorage } from '@/storage'
import { defaultAudioHistoryStorage } from '@/storage/defaults'
import { useIntervalFn } from '@vueuse/core'

const loading = ref(false)
const playing = ref(false)

const options = [
  { label: '热歌榜', value: '热歌榜' },
  { label: '新歌榜', value: '新歌榜' },
  { label: '飙升榜', value: '飙升榜' },
  { label: '原创榜', value: '原创榜' }
]

// 当前播放
const state = reactive<AudioType>(Local.get('home_audio') || defaultAudioHistoryStorage()[0])

const volume = ref(100)
const current = ref(0)
const duration = ref(0)
const currentTime = ref('00:00')
const durationTime = ref('00:00')

let sound: Howl

const { pause, resume } = useIntervalFn(() => {
  if (sound) {
    playing.value = sound.playing()
    current.value = Math.ceil(sound.seek())
    duration.value = Math.ceil(sound.duration())
    currentTime.value = formatTrackTime(unref(current))
    durationTime.value = formatTrackTime(unref(duration))
  }
}, 1000)

const onPause = () => {
  if (!sound) {
    onPlay()
  } else {
    if (playing.value) {
      sound.pause()
      playing.value = false
      pause()
    } else {
      sound.play()
      playing.value = true
      resume()
    }
  }
}

const onPlay = async () => {
  loading.value = true

  // 回收所有播放的进程
  Howler.unload()

  // 初始化播放
  sound = new Howl({
    src: [state.url],
    html5: true,
    autoplay: true,
    volume: unref(volume) / 100,
    format: ['mp3', 'acc', 'flac']
  })
  sound.on('loaderror', (soundId, error) => {
    console.log('loaderror')
    if (error === 4) {
      onNext()
      console.log('无法播放: 不支持的音频格式')
    } else {
      console.log('Error', soundId, error)
    }
    loading.value = false
  })

  sound.once('load', () => {
    loading.value = false
    playing.value = true
    plusHistory()
  })
  sound.once('end', () => {
    console.log('end')
    playing.value = false
    // 下一首
    onNext()
  })
}

const onNext = async () => {
  loading.value = true
  const { info, sort } = await fetch(
    `https://api.vvhan.com/api/wyMusic/${state.sort}?type=json`
  ).then((res) => res.json())
  setState(info, sort)
  await onPlay()
}

const setState = (info: AudioType, sort?: string) => {
  state.sort = sort || info.sort
  state.id = info.id
  state.name = info.name
  state.auther = info.auther
  state.url = info.url
  state.picUrl = info.picUrl || info.pic_url
  Local.set('home_audio', state)
}

const plusHistory = () => {
  if (!audioHistoryStorage.value.some((s) => s.id === state.id)) {
    audioHistoryStorage.value.unshift(JSON.parse(JSON.stringify(state)))
  }
}

const formatTooltip = (value: number) => {
  return value + '%'
}

const formatTooltip2 = (value: number) => {
  return formatTrackTime(value)
}

const onSliderChange = (value: number) => {
  sound?.seek(value)
}

const onCommand = (id: number) => {
  const item = audioHistoryStorage.value.find((f) => f.id === id)
  if (item) {
    playing.value = false
    setState(item)
    onPlay()
  }
}

watch(volume, (value) => {
  sound?.volume(value / 100)
})

onActivated(() => {
  resume()
})

onDeactivated(() => {
  pause()
})
</script>

<template>
  <div class="home-audio h100 color-white" :style="{ backgroundImage: `url(${state.picUrl})` }">
    <div class="home-audio-mask"></div>
    <div class="home-audio-content flex flex-column px5 pt5 text-center">
      <div class="w100 flex align-center justify-between home-audio-content-select">
        <el-select v-model="state.sort">
          <el-option
            v-for="(item, index) in options"
            :key="index"
            :value="item.value"
            :label="item.label"
          ></el-option>
        </el-select>
        <el-dropdown trigger="click" @command="onCommand">
          <el-button>
            历史记录 [{{ audioHistoryStorage.length }}]
            <el-icon class="el-icon--right">
              <ArrowDown />
            </el-icon>
          </el-button>
          <template #dropdown>
            <el-dropdown-menu style="max-height: 50vh">
              <el-dropdown-item
                v-for="(item, index) in audioHistoryStorage"
                :key="index"
                :command="item.id"
                :disabled="item.id === state.id"
              >
                《{{ item.name }}》{{ item.auther }}
              </el-dropdown-item>
            </el-dropdown-menu>
          </template>
        </el-dropdown>
      </div>
      <div class="mb5 mt32 font-bold font16">{{ state.name }}</div>
      <div class="font12">{{ state.auther }}</div>
      <div class="my10">
        <el-button
          :disabled="loading"
          :icon="CaretLeft"
          circle
          class="font18 pa1 width-auto height-auto"
          @click="onNext"
        ></el-button>
        <el-button
          v-if="!playing"
          :loading="loading"
          :icon="VideoPlay"
          circle
          type="primary"
          class="font30 pa1 width-auto height-auto ml20"
          @click="onPause"
        ></el-button>
        <el-button
          v-else
          :loading="loading"
          :icon="VideoPause"
          circle
          type="danger"
          class="font30 pa1 width-auto height-auto ml20"
          @click="onPause"
        ></el-button>
        <el-button
          :disabled="loading"
          :icon="CaretRight"
          circle
          class="font18 pa1 width-auto height-auto ml20"
          @click="onNext"
        ></el-button>
      </div>
      <div class="flex justify-between">
        <span>来一首歌放松心情吧~</span>
        <div class="flex align-center justify-center">
          <div style="width: 80px; transform: translateX(-10px)" class="flex align-center">
            <el-icon>
              <Headset />
            </el-icon>
            <el-slider
              v-model="volume"
              :step="1"
              :min="0"
              :max="100"
              class="ml5"
              :format-tooltip="formatTooltip"
            />
          </div>
        </div>
      </div>
      <div class="flex align-center">
        <span class="mr10">{{ currentTime }}</span>
        <el-slider
          v-model="current"
          :min="0"
          :max="duration"
          :format-tooltip="formatTooltip2"
          @change="onSliderChange"
        />
        <span class="ml10">{{ durationTime }}</span>
      </div>
    </div>
  </div>
</template>
<style lang="scss">
.home-audio {
  background-repeat: no-repeat;
  background-size: cover;
  background-position: center center;
  position: relative;
  border-radius: 4px;
  overflow: hidden;

  &:hover {
    .home-audio-mask {
      background-color: rgba(0, 0, 0, 0.7);
    }
  }

  .home-audio-mask {
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    background-color: rgba(0, 0, 0, 0.3);
    transition: background-color ease-in-out 0.3s;
    z-index: 0;
  }

  .home-audio-content {
    position: relative;
    z-index: 1;
    width: 100%;
    height: 100%;

    .home-audio-content-select {
      .el-select {
        width: 100px;
      }

      .el-button {
        color: #ededed !important;
        background-color: transparent !important;
        border-color: #ededed !important;
      }

      .el-select__wrapper {
        background-color: transparent !important;
        box-shadow: 0 0 0 1px #ededed inset;
      }

      .el-select__caret,
      .el-select__placeholder {
        color: #ededed !important;
      }
    }
  }
}
</style>
